import { Client, ReconnectionTimeMode } from "@stomp/stompjs";
import TokenManager from "@/utils/token-utils";
import runtimeConfig from "@/config/runtime";
import StompSubscriptionManager from "@/services/stomp/stomp-subscription";
import * as Device from "expo-device";

/**
 * Stomp客户端管理器
 */
class StompClientManager {
    private client: Client | null = null;
    private connected = false;
    private readonly subscribeManager = new StompSubscriptionManager();

    public getClient(): Client | null {
        return this.client;
    }

    public isConnected(): boolean {
        return this.connected && !!this.client?.connected;
    }

    public connect() {
        if (this.client && this.client.connected) return;

        const token = TokenManager.getToken();
        if (!token) return;

        const client = new Client({
            brokerURL: runtimeConfig.WS_URL,
            connectHeaders: {
                "Authorization": token,
                "X-Device-Id": Device.osInternalBuildId,
                "X-Device-Name": Device.deviceName || "Unknown Device",
                "X-Device-Type": Device.deviceType.toString() || "Unknown"
            },
            reconnectDelay: 1000,
            reconnectTimeMode: ReconnectionTimeMode.EXPONENTIAL,
            maxReconnectDelay: 10000,
            heartbeatIncoming: 5000,
            heartbeatOutgoing: 5000,
            webSocketFactory: () => new WebSocket(runtimeConfig.WS_URL),
            forceBinaryWSFrames: true,
            appendMissingNULLonIncoming: true,

            onConnect: () => {
                console.log("[STOMP] Connected!");
                this.connected = true;
                this.subscribeManager.setUpSubscriptions(client);
            },
            onDisconnect: () => {
                console.warn("[STOMP] Disconnected.");
                this.connected = false;
                this.subscribeManager.unsubscribeAll();
            },
            onWebSocketClose: () => {
                console.warn("[STOMP] WebSocket closed.");
                this.connected = false;
                this.subscribeManager.unsubscribeAll();
            },
            onStompError: (frame) => {
                console.error("[STOMP] STOMP Error:", frame.body);
            },
        });

        this.client = client;
        client.activate();
    }

    public disconnect() {
        this.subscribeManager.unsubscribeAll();
        this.client?.deactivate();
        this.client = null;
        this.connected = false;
    }
}

export default new StompClientManager();
